package mybox.engine;

public class RandLinie implements Figur{
	
	public static final String BREITE="BREITE";
	public static final String HOEHE="HOEHE";
	public static final String LAENGE="LAENGE";
	
	public static final String M="M";
	public static final String F="F";
	public static final String FX="FX";
	public static final String MR="MR";
	public static final String MX="MX";
	
	public static final boolean ISGLATT=true;
	public static final boolean ISNOTGLATT=false;
	
	public String type;
	public int    anzahlZinken;
	public double randLaenge;
	public double zinkenHoehe;
	public double zinkenABreite;
	public double zinkenIBreite;
	public boolean isGlatt;
	
	double mZinkenIBreite;
    double mZinkenABreite;
    double mrandLaenge;
	
	public String mfType;
	public File4Qcad file4qcad=null;
	public double linienlaenge;
	public double xLaenge;
	public double materialDicke;
	
	public double laserBreite;
	public QVector aktPos;
	
	public QVector beginPoint;
	public QVector endPoint;
	
	
	 QVector rausVec;        
	 QVector zinkenABreiteVec;
	 QVector reinVec;    
	 QVector zinkenIBreiteVec;
	 QVector zinkenRBreiteVec;
	 
	 
	 QVector mRausVec; 
     QVector mZinkenABreiteVec;
     QVector mReinVec;    
     QVector mZinkenIBreiteVec;
     QVector mZinkenRBreiteVec;
     
     QVector xRausVec;
     QVector xReinVec;
     QVector xBreiteVec;
     
     public RandLinie(
 			File4Qcad file4qcad, 
 			QVector aktPos, 			 
 			String mfType,
 			double phi,
 			double linienLaenge, 			
 			double materialDicke, 
 			double zinkungsFaktor,
 			double laserBreite) {
    	 
    	 init(file4qcad, 
 				aktPos, 			 
 				mfType,
 				phi,
 				linienLaenge,
 				0,
 				materialDicke, 
 				zinkungsFaktor,
 				laserBreite,
 				ISNOTGLATT);
    	 
     }
     
     public RandLinie(
  			File4Qcad file4qcad, 
  			QVector aktPos, 			 
  			String mfType,
  			double phi,
  			double linienLaenge, 			
  			double materialDicke,
            double zinkungsFaktor,
  			double laserBreite,
  			boolean isGlatt) {
     	 
     	 init(file4qcad, 
  				aktPos, 			 
  				mfType,
  				phi,
  				linienLaenge,
  				0,
  				materialDicke,
  				zinkungsFaktor,
  				laserBreite,
  				isGlatt);
     	 
      }
     
     
	
	public RandLinie(
			File4Qcad file4qcad, 
			QVector aktPos, 			 
			String mfType,
			double phi,
			double linienLaenge,
			double xLaenge,
			double materialDicke, 
			double zinkungsFaktor,
			double laserBreite,
			boolean isGlatt) {		
		init(file4qcad, 
				aktPos, 			 
				mfType,
				phi,
				linienLaenge,
				xLaenge,
				materialDicke, 
				zinkungsFaktor,
				laserBreite,
				isGlatt);
		  
	}
	
	public void init(File4Qcad file4qcad, 
			QVector aktPos, 			 
			String mfType,
			double phi,
			double linienLaenge,
			double xLaenge,
			double materialDicke, 
			double zinkungsFaktor,
			double laserBreite,
			boolean isGlatt) {
		
		this.mfType=mfType;		
		this.file4qcad=file4qcad;
		this.linienlaenge=linienLaenge;
		this.xLaenge=xLaenge;
		this.materialDicke=materialDicke;
		
		this.laserBreite=laserBreite;
		this.aktPos=aktPos;
		this.beginPoint = new QVector(aktPos.x, aktPos.y);
		this.isGlatt=isGlatt;
		
		
		 anzahlZinken=anzahlZinken(linienLaenge,materialDicke, zinkungsFaktor, laserBreite);
		 
		 		
		 this.zinkenHoehe=calcZinkenHoehe(materialDicke);
		 zinkenABreite=aBreite(materialDicke,zinkungsFaktor);
		 zinkenIBreite=iBreite(zinkenABreite,laserBreite);
		 randLaenge=randBreite(mfType.equalsIgnoreCase(MR), linienLaenge, materialDicke, zinkungsFaktor, laserBreite);
		 
		  
		 mZinkenIBreite=zinkenABreite+laserBreite;
		 mZinkenABreite=zinkenIBreite-laserBreite;
		 mrandLaenge=randLaenge-laserBreite;
				 
		  rausVec				= rotateVec(phi,new QVector(0,-zinkenHoehe));        
		  zinkenABreiteVec		= rotateVec(phi,new QVector(zinkenABreite,0));
		  reinVec				= rotateVec(phi,new QVector(0,zinkenHoehe));    
		  zinkenIBreiteVec		= rotateVec(phi,new QVector(zinkenIBreite,0));
		  zinkenRBreiteVec 		= rotateVec(phi,new QVector(randLaenge,0));
		 		 		  
		  mRausVec				= rotateVec(phi,new QVector(0,zinkenHoehe));
          mZinkenABreiteVec		= rotateVec(phi, new QVector(mZinkenABreite,0));
          mReinVec				= rotateVec(phi, new QVector(0,-zinkenHoehe));    
          mZinkenIBreiteVec		= rotateVec(phi,new QVector(mZinkenIBreite,0));
          mZinkenRBreiteVec 	= rotateVec(phi,new QVector(mrandLaenge,0));
          
          xRausVec				= rotateVec(phi,new QVector(0,-xLaenge));
          xReinVec 				= rotateVec(phi,new QVector(0,xLaenge));
          xBreiteVec			= rotateVec(phi, new QVector(linienLaenge,0));
		 		 		
	}
	
	
	public static double calcZinkenHoehe(double materialDicke) {
		return materialDicke;
	}
	
	/**Rotiert einen Vector um den angegeben Winkel*/
	public static QVector rotateVec(double phi, QVector qvector) {
		
		double cosPhi=java.lang.Math.cos(phi);
		double sinPhi=java.lang.Math.sin(phi);
		
		QVector rotatedVector = new QVector (cosPhi*qvector.x-sinPhi*qvector.y,sinPhi*qvector.x+cosPhi*qvector.y);
		
		return rotatedVector;
		
	}
	
	/**Die aeussere ZinkBreite*/
	public static double aBreite(double materialDicke, double zinkungsFaktor) {
	   return materialDicke*zinkungsFaktor;
	}

	/**Die innere ZinkBreite*/
	public static double iBreite(double aBreite, double laserBreite) {
	  return aBreite-laserBreite;
	}



	/**Die RandLenge einer Zinkung, d.h. aeussere plus innere Laenge*/
	public static double zLaenge(double materialDicke, double zinkungsFaktor, double laserBreite) {
	    double taBreite=aBreite(materialDicke, zinkungsFaktor);    
	    return taBreite+iBreite(taBreite,laserBreite);
	}

	/**Berechnet die Anzahl der Zinken fuer eine gewuenschte
	Laenge, materialDicke und LaserBreite*/
	public static int anzahlZinken(double seitenLaenge, double materialDicke, double zinkungsFaktor, double laserBreite) {
	  
	    double tredLaenge = redLaenge(seitenLaenge, materialDicke, zinkungsFaktor, laserBreite);     
	    double divisor=zLaenge(materialDicke, zinkungsFaktor, laserBreite);
	    int tZinkenAnzahl=intDiv(tredLaenge,divisor)+2;
	    
	    return tZinkenAnzahl;  
	}

	/**Berechnet die Laenge des Randes bezogen auf die gegebenen Parameter*/
	public static double randBreite(boolean randVerkuerzt, double seitenLaenge, double materialDicke, double zinkungsFaktor, double laserBreite) {
	  
	  int tZinkenAnzahl=anzahlZinken(seitenLaenge, materialDicke, zinkungsFaktor, laserBreite);
	  
	  double tZinkRBreiteS=redLaenge(seitenLaenge, materialDicke, zinkungsFaktor, laserBreite)/2
	                    -(tZinkenAnzahl-2)*zLaenge(materialDicke, zinkungsFaktor, laserBreite)/2;
	  double tZinkRBreite=3*aBreite(materialDicke, zinkungsFaktor)/2+tZinkRBreiteS;
	  
	  //if (mfType.equalsIgnoreCase(MR)) tZinkRBreite-=materialDicke;		
	  if (randVerkuerzt) tZinkRBreite-=materialDicke;	
	  
	  return tZinkRBreite;
	  
	}

	/**Die reduzierte Laenge aus der Zinkungsformel*/
	public static double redLaenge(double seitenLaenge, double materialDicke, double zinkungsFaktor, double laserBreite) {
	    double tZinkABreite=aBreite(materialDicke, zinkungsFaktor);
	    double tZinkIBreite=iBreite(tZinkABreite,laserBreite);
	    
	    return seitenLaenge-tZinkIBreite-3*tZinkABreite;
	  
	}
	
	public static int intDiv(double x, double divisor) {
		  return (int)((x-0.000000001)/divisor);
		}

	public void draw() {
		draw(true);
	}
	public void draw(boolean reallyDraw) {
		
		//Female Zinkung
		if (mfType.equalsIgnoreCase(F)) {			
		for (int zinkIdx=0;zinkIdx<anzahlZinken-1;zinkIdx+=1) {
	         if (zinkIdx>0) {
	        	if (!isGlatt) file4qcad.println(rausVec.printLine(aktPos,reallyDraw));
	 			file4qcad.println(zinkenABreiteVec.printLine(aktPos,reallyDraw));	
	         }
	         else  
	        file4qcad.println(zinkenRBreiteVec.printLine(aktPos,reallyDraw));	
		    
	        if (!isGlatt) file4qcad.println(reinVec.printLine(aktPos,reallyDraw));
			file4qcad.println(zinkenIBreiteVec.printLine(aktPos,reallyDraw));
	         
	     }

		if (!isGlatt) file4qcad.println(rausVec.printLine(aktPos,reallyDraw));
		file4qcad.println(zinkenRBreiteVec.printLine(aktPos,reallyDraw));
		} 
		
		//xFemale Zinkung
		if (mfType.equalsIgnoreCase(FX)) {
		QVector aktPosBegin = new QVector(aktPos);
		for (int zinkIdx=0;zinkIdx<anzahlZinken-1;zinkIdx+=1) {
	         if (zinkIdx>0) {
	        	if (!isGlatt) file4qcad.println(rausVec.printLine(aktPos,reallyDraw));
	 			file4qcad.println(zinkenABreiteVec.noPrintLine(aktPos));	
	         }
	         else  
	        file4qcad.println(zinkenRBreiteVec.noPrintLine(aktPos));
	         
	        if (reallyDraw) file4qcad.println(zinkenIBreiteVec.printLineAktPosNeutral(aktPos));
	        if (!isGlatt) file4qcad.println(reinVec.printLine(aktPos,reallyDraw));
			file4qcad.println(zinkenIBreiteVec.printLine(aktPos,reallyDraw));
	         
	     }

		if (!isGlatt) file4qcad.println(rausVec.printLine(aktPos,reallyDraw));
		file4qcad.println(zinkenRBreiteVec.noPrintLine(aktPos));
		
		if (!isGlatt) file4qcad.println(xRausVec.printLine(aktPosBegin,reallyDraw));
		file4qcad.println(xBreiteVec.printLine(aktPosBegin,reallyDraw));
		if (!isGlatt) file4qcad.println(xReinVec.printLine(aktPosBegin,reallyDraw));
		
		} 
		
		//Male Zinkung
		if (mfType.equalsIgnoreCase(M)||mfType.equalsIgnoreCase(MR)) {
		
			for (int zinkIdx=0;zinkIdx<anzahlZinken-1;zinkIdx+=1) {
		         if (zinkIdx>0) {
		        	if (!isGlatt) file4qcad.println(mRausVec.printLine(aktPos,reallyDraw));
		 			file4qcad.println(mZinkenABreiteVec.printLine(aktPos,reallyDraw));	
		         }
		         else  
		        file4qcad.println(mZinkenRBreiteVec.printLine(aktPos,reallyDraw));	
			    
		        if (!isGlatt) file4qcad.println(mReinVec.printLine(aktPos,reallyDraw));
				file4qcad.println(mZinkenIBreiteVec.printLine(aktPos,reallyDraw));
		         
		     }

			if (!isGlatt) file4qcad.println(mRausVec.printLine(aktPos,reallyDraw));
			file4qcad.println(mZinkenRBreiteVec.printLine(aktPos,reallyDraw));	
		}
		
		//xMale Zinkung
		if (mfType.equalsIgnoreCase(MX)) {
			QVector aktPosBegin = new QVector(aktPos);
			for (int zinkIdx=0;zinkIdx<anzahlZinken-1;zinkIdx+=1) {
		         if (zinkIdx>0) {
		        	if (!isGlatt) file4qcad.println(mRausVec.printLine(aktPos,reallyDraw));
		        	//file4qcad.println(mZinkenABreiteVec.printLine(aktPos,reallyDraw));	
		 			file4qcad.println(mZinkenABreiteVec.noPrintLine(aktPos));	
		         }
		         else  
		        //file4qcad.println(mZinkenRBreiteVec.printLine(aktPos,reallyDraw));	
		        file4qcad.println(mZinkenRBreiteVec.noPrintLine(aktPos));	
			    
		        if (reallyDraw) file4qcad.println(zinkenIBreiteVec.printLineAktPosNeutral(aktPos)); 
		        if (!isGlatt) file4qcad.println(mReinVec.printLine(aktPos,reallyDraw));
				file4qcad.println(mZinkenIBreiteVec.printLine(aktPos,reallyDraw));
		         
		     }

			if (!isGlatt) file4qcad.println(mRausVec.printLine(aktPos,reallyDraw));
			file4qcad.println(mZinkenRBreiteVec.printLine(aktPos,reallyDraw));	
			
			
			if (!isGlatt) file4qcad.println(xRausVec.printLine(aktPosBegin,reallyDraw));
			file4qcad.println(xBreiteVec.printLine(aktPosBegin,reallyDraw));
			if (!isGlatt) file4qcad.println(xReinVec.printLine(aktPosBegin,reallyDraw));
			
		}	
	
		this.endPoint = new QVector(aktPos.x, aktPos.y);
		
	}
	
	

}
